package com.csmht.tododemo.service.impl;

import com.csmht.tododemo.constant.MessageConstant;
import com.csmht.tododemo.exiception.BaseException;
import com.csmht.tododemo.mapper.BanMapper;
import com.csmht.tododemo.mapper.CreateAdminMapper;
import com.csmht.tododemo.mapper.UserMapper;
import com.csmht.tododemo.pojo.dto.UserDTO;
import com.csmht.tododemo.pojo.entity.Ban;
import com.csmht.tododemo.pojo.entity.CreateAdmin;
import com.csmht.tododemo.pojo.entity.Role;
import com.csmht.tododemo.pojo.entity.User;
import com.csmht.tododemo.pojo.enumeration.RoleEnum;
import com.csmht.tododemo.properties.JwtProperties;
import com.csmht.tododemo.service.UserService;
import com.csmht.tododemo.until.JwtUntil;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.beans.Transient;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * UserServiceImpl - 用户业务逻辑实现类
 * 实现UserService接口定义的用户认证与管理功能
 * 主要功能包括：
 * 1. 用户登录认证(包含密码加密验证)
 * 2. 用户注册(包含数据校验和密码加密存储)
 * 使用MD5算法进行密码加密，确保数据安全
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private BanMapper banMapper;

    @Resource
    private JwtProperties jwtProperties;

    @Resource
    private CreateAdminMapper createAdminMapper;

    /**
     * 用户登录认证方法
     * @param userLoginDTO 登录请求数据传输对象，包含手机号和密码
     * @return 登录成功返回用户基本信息(仅包含ID和角色)
     * @throws BaseException 当手机号不存在或密码错误时抛出
     */
    public Map<String,Object> login(UserDTO userLoginDTO) {

        // 获取登录手机号和密码
        String phone = userLoginDTO.getPhone();
        String password = userLoginDTO.getPassword();

        // 根据手机号查询用户信息
        User login = userMapper.login(phone);

        // 验证用户是否存在
        if(login == null){
            throw new BaseException(MessageConstant.NO_PHONE); // 手机号不存在异常
        }

        // 对输入密码进行MD5加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        // 验证密码是否匹配
        if(!password.equals(login.getPassword())){
            throw new BaseException(MessageConstant.PASSWORD_ERR); // 密码错误异常
        }

        // 登录成功，获取用户角色
        Role role =Role.builder().build();

        role.setId(login.getId());

        List<Ban> banTimeByUserId = banMapper.getBanTimeByUserId(login.getId(), LocalDateTime.now());

        if(!banTimeByUserId.isEmpty()){
            role.setRole(RoleEnum.BAN_USER);
        }else if(login.getRole() == 1){
            role.setRole(RoleEnum.ADMIN);
        }else{
            role.setRole(RoleEnum.USER);
        }

        Map<String,Object> map = new HashMap<>();
        map.put("role",role);

        String jwt = JwtUntil.createJWT(jwtProperties.getSecretKey(), jwtProperties.getTtl(), map);

        return new HashMap<>(){{
            put(jwtProperties.getTokenName(),jwt);
        }};
    }



    /**
     * 用户注册方法
     * @param user 注册请求数据传输对象，包含用户基本信息
     * @throws BaseException 当输入数据不完整或手机号已被注册时抛出
     */
    @Override
    public void register(UserDTO user) {

        // 验证输入数据完整性
        if(user == null || user.getPhone() == null || user.getPassword() == null){
            throw new BaseException(MessageConstant.DATE_MISS); // 数据缺失异常
        }

        // 检查手机号是否已被注册
        User login = userMapper.login(user.getPhone());
        if(login != null){
            throw new BaseException(MessageConstant.PHONE_MORE); // 手机号已存在异常
        }

        // 转换DTO为实体对象
        User user1 = User.builder().build();
        BeanUtils.copyProperties(user, user1);

        // 密码加密处理(MD5算法)
        user1.setPassword(DigestUtils.md5DigestAsHex(user1.getPassword().getBytes()));
        // 设置创建时间
        user1.setCreateTime(LocalDateTime.now());
        // 保存新用户到数据库
        userMapper.insert(user1);

    }


    @Override
    @Transient
    public void addAdmin(Long userId) {
        userMapper.updateAdmin(userId,1L);

        CreateAdmin createAdmin = new CreateAdmin();

        createAdmin.setUserId(userId);

        createAdminMapper.inset(createAdmin);

    }
}